home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1992 June: ROMin Holiday / ADC Developer CD (1992-06) (''ROMin Holiday'')_iso / Developer Connection - 06-1992.iso / Developer Essentials / DTS Sample Code / System 7.0 Samples / ProcDoggie 1.0a6⁄THINK P / ProcDoggie.p < prev    next >
Encoding:
Text File  |  1991-02-21  |  18.3 KB  |  573 lines  |  [TEXT/PJMM]

  1. program ProcDoggie;
  2.  
  3. {-------------------------------------------------------------------------------}
  4. {#}
  5. {#    Apple Macintosh Developer Technical Support}
  6. {#}
  7. {#    Main program file for the ProcDoggie application}
  8. {#}
  9. {#    Program:    ProcDoggie}
  10. {#    File:        ProcDoggie.p - Pascal Implementation}
  11. {#}
  12. {#    by:        Forrest Tanaka}
  13. {#}
  14. {#    Copyright © 1988-1991 Apple Computer, Inc.}
  15. {#    All rights reserved.}
  16. {#}
  17. {--------------------------------------------------------------------------------}
  18. {#}
  19. {#    ProcDoggie.p is the root file for ProcDoggie.  It contains the main entry}
  20. {#    point and the PROGRAM statement, but relies on the other source files}
  21. {#    included with this application to actually implement the functionality.}
  22. {#}
  23. {-------------------------------------------------------------------------------}
  24. {[j=20/57/1$] Pasmat Options}
  25. {$R-}
  26.  
  27. {-------------------------------------------------------------------------------}
  28. {#}
  29. {#     2/21/91 pvh - THINK Pascal conversion.}
  30. {#    Notes:}
  31. {#        'uses' modified heavily in each unit to handle toolbox references.}
  32. {#}
  33. {-------------------------------------------------------------------------------}
  34.  
  35. {$IFC THINK_PASCAL }
  36. {$I- turn off auto init stuff }
  37. {$ENDC}
  38.  
  39. (*******************************************************************************}
  40. {* Used Units}
  41. {*******************************************************************************)
  42.  
  43.     uses
  44.         (* Group 1 *)
  45.         Types, QuickDraw, 
  46.  
  47.         (* Group 2 *)
  48.         AppleTalk, PPCToolBox, OSUtils, Files, Processes, EPPC, Notification, AppleEvents, Controls, DiskInit, Errors, Events, Fonts, Memory, Menus, SegLoad, 
  49.  
  50.         (* Group 3 *)
  51.         Windows, 
  52.  
  53.         (* Group 4 *)
  54.         Dialogs, 
  55.  
  56.         (* Application *)
  57.         UGlobals, UEmergMem, UProcessUtils, {UMenuHandler, }
  58.         UProcessGuts;
  59.  
  60.  
  61. (*******************************************************************************}
  62. {* Constants}
  63. {*******************************************************************************)
  64.  
  65.     const
  66.         kBecomingActive = TRUE; {Pass to DoActivateEvt; indicates becoming active}
  67.  
  68.  
  69. (*******************************************************************************}
  70. {* Global Variables}
  71. {*******************************************************************************)
  72.  
  73.     var
  74.         gProcessListWind: WindowPtr; {Pointer to the process list window}
  75.  
  76.  
  77. {$S Main}
  78. (*******************************************************************************}
  79. {* DoneRequiredParams - Done processing required params; OK?}
  80. {*}
  81. {* DoneRequiredParams checks to see if the AppleEvent specified by the}
  82. {* anAppleEvent parameter has any required parameters that we haven’t yet}
  83. {* processed.  If there aren’t any left, then noErr is returned.  If there are}
  84. {* required parameters that haven’t been processed yet, then errAEEventNotHandled}
  85. {* is returned.  If any other errors occur, then that error code is returned.}
  86. {*******************************************************************************)
  87.  
  88.     function DoneRequiredParams (anAppleEvent: AppleEvent): OSErr;
  89.  
  90.         var
  91.             typeCode: DescType; {Type of AppleEvent attribute found; ignored}
  92.             actualSize: Size;     {Actual size of parameters; ignored}
  93.             error: OSErr;
  94.  
  95.     begin
  96.         (* Are there any required parameters in AppleEvent we didn’t process? *)
  97.         error := AEGetAttributePtr(anAppleEvent, keyMissedKeywordAttr, typeWildCard, typeCode, nil, 0, actualSize); (*<*)
  98.  (*<*)
  99.         if error = errAEDescNotFound then
  100.             (* No required parameters left, so no error *)
  101.             DoneRequiredParams := noErr
  102.         else if error = noErr then
  103.             (* There was at least one required parameter we didn’t process *)
  104.             DoneRequiredParams := errAEEventNotHandled
  105.         else
  106.             (* Some other error happened *)
  107.             DoneRequiredParams := error
  108.     end;
  109.  
  110.  
  111. {$S Main}
  112. (*******************************************************************************}
  113. {* HandleAEquit - Handler for 'quit' AppleEvent}
  114. {*}
  115. {* This is the AppleEvent handler for the 'quit' AppleEvent as passed in the}
  116. {* quitAppleEvent parameter by the AppleEvent Manager.  The DoQuit routine is}
  117. {* called which causes this application to quit at the start of the next}
  118. {* iteration of the main event loop.}
  119. {*}
  120. {* Though the quit AppleEvent doesn’t contain any parameters, the standard thing}
  121. {* to do in reaction to any AppleEvent is to check to see if there are any}
  122. {* required parameters in the AppleEvent that this routine doesn’t recognise.}
  123. {* DoneRequiredParms checks for this condition and returns an error if there are}
  124. {* in fact required parameters in the AppleEvent or if some other error occurs}
  125. {* during the check.}
  126. {*******************************************************************************)
  127.  
  128.     function HandleAEquit (quitAppleEvent: AppleEvent; reply: AppleEvent; handlerRefCon: LongInt): OSErr;
  129.  
  130.         var
  131.             error: OSErr;
  132.  
  133.         procedure RecoverError (errorCode: OSErr);
  134.  
  135.         begin
  136.             HandleAEquit := errorCode;
  137.             EXIT(HandleAEquit)
  138.         end;
  139.  
  140.     begin
  141.         (* quit AE has no parms, but check in case the client requires any *)
  142.         error := DoneRequiredParams(quitAppleEvent);
  143.         if error <> noErr then
  144.             RecoverError(error);
  145.  
  146.         (* Handle the Quit command *)
  147.         DoQuit;
  148.         HandleAEquit := noErr
  149.     end;
  150.  
  151.  
  152. {$S %A5Init}
  153. (*******************************************************************************}
  154. {* StartUp - Do whatever has to be done to initialize the application}
  155. {*}
  156. {* This routine is called after the heap is initialized to initialize the}
  157. {* application.  This involves initializing the toolbox, emergency memory, and}
  158. {* loading up the menus.  If any errors occur while doing this, StartUp displays}
  159. {* an alert telling the user what the error was and then ExitToShell is called.}
  160. {* This is an unusual way to react to errors, and I only do it here because it’s}
  161. {* so early in execution that there really isn’t much else that can be done.}
  162. {*}
  163. {* See this UEmergMem unit in this application for details about emergency}
  164. {* memory.}
  165. {*******************************************************************************)
  166.  
  167.     procedure StartUp;
  168.  
  169.         const
  170.             kSysHandler = TRUE; {Specifies that AE handler is in system heap}
  171.  
  172.         var
  173.             error: OSErr;
  174.  
  175.         procedure HandleError (messageClass: Integer; messageIndex: Integer);
  176.  
  177.             var
  178.                 result: Integer; {Result of alert; ignored}
  179.  
  180.         begin
  181.             result := ShowStopAlert(messageClass, messageIndex);
  182.             ExitToShell
  183.         end;
  184.  
  185.     begin
  186.         (* Initialize the toolbox *)
  187.         InitGraf(@thePort);
  188.         InitFonts;
  189.         InitWindows;
  190.         InitMenus;
  191.         TEInit;
  192.         InitDialogs(nil);
  193.  
  194.         (* Initialize emergency memory *)
  195.         InitEmergMem;
  196.         if FailLowMemory(0) then
  197.             HandleError(rMemErrMessages, kMemErrAppOpenMsg);
  198.  
  199.         (* Load the menus and draw the menu bar *)
  200.         StartMenus;
  201.         if FailLowMemory(0) then
  202.             HandleError(rMemErrMessages, kMemErrAppOpenMsg)
  203.         else if gError <> noErr then
  204.             if gError = memFullErr then
  205.                 HandleError(rMemErrMessages, kMemErrAppOpenMsg)
  206.             else if gError = resNotFound then
  207.                 HandleError(rResErrMessages, kResErrAppDamageMsg)
  208.             else
  209.                 HandleError(rMiscErrMessages, kMiscErrUnknownMsg);
  210.  
  211.         (* Install the AppleEvent handler *)
  212.         error := AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, @HandleAEquit, 0, not kSysHandler);
  213.         if (error = memFullErr) | FailLowMemory(0) then
  214.             HandleError(rMemErrMessages, kMemErrAppOpenMsg)
  215.         else if error <> noErr then
  216.             HandleError(rMiscErrMessages, kMiscErrUnknownMsg)
  217.     end;
  218.  
  219.  
  220. {$S Main}
  221. (*******************************************************************************}
  222. {* Public: DoWindowDrag}
  223. {*}
  224. {* A rectangle that covers all screen can be retrieved from the desktop region’s}
  225. {* rgnBBox.  The desktop region can be retrieved by calling GetGrayRgn.}
  226. {*******************************************************************************)
  227.  
  228.     procedure DoWindowDrag (anEvent: EventRecord; clickedWindow: WindowPtr);
  229.  
  230.         var
  231.             dragBounds: Rect; {Window can be dragged over this rectangle}
  232.  
  233.     begin
  234.         (* GetGrayRgn^^.rgnBBox covers the desktop over all screens *)
  235.         dragBounds := GetGrayRgn^^.rgnBBox;
  236.         DragWindow(clickedWindow, anEvent.where, dragBounds)
  237.     end;
  238.  
  239.  
  240. {$S Main}
  241. (*******************************************************************************}
  242. {* Public: DoContentClick}
  243. {*}
  244. {* As new kinds of windows are added to this application, this routine will have}
  245. {* to be able to detect the new kind of window and dispatch to the routine that}
  246. {* handles clicks in that kind of window.}
  247. {*******************************************************************************)
  248.  
  249.     procedure DoContentClick (anEvent: EventRecord; clickedWindow: WindowPtr);
  250.  
  251.         var
  252.             currWindow: WindowPtr; {Pointer to the current front window}
  253.  
  254.     begin
  255.         currWindow := FrontWindow;
  256.  
  257.         (* Clicked window not in front; activate it *)
  258.         if currWindow <> clickedWindow then
  259.             SelectWindow(clickedWindow)
  260.         else if IsProcessListWindow(clickedWindow) then
  261.             ClickProcessListWindow(clickedWindow, anEvent)
  262.     end;
  263.  
  264.  
  265. {$S Main}
  266. (*******************************************************************************}
  267. {* Public: DoUpdateEvt}
  268. {*}
  269. {* As new kinds of windows are added to this application, this routine will have}
  270. {* to be able to detect the new kind of window and dispatch to the routine that}
  271. {* handles update events in that kind of window.}
  272. {*******************************************************************************)
  273.  
  274.     procedure DoUpdateEvt (anEvent: EventRecord);
  275.  
  276.         var
  277.             eventWindow: WindowPtr; {Pointer to the window to update}
  278.  
  279.     begin
  280.         eventWindow := WindowPtr(anEvent.message);
  281.  
  282.         (* Update the window that needs it *)
  283.         SetPort(eventWindow);
  284.         BeginUpdate(eventWindow);
  285.         if IsProcessListWindow(eventWindow) then
  286.             DrawProcessListWindow(eventWindow)
  287.         else if IsProcessInfoWindow(eventWindow) then
  288.             DrawProcessInfoWindow(eventWindow);
  289.         EndUpdate(eventWindow)
  290.     end;
  291.  
  292.  
  293. {$S Main}
  294. (*******************************************************************************}
  295. {* Public: DoActivateEvt}
  296. {*}
  297. {* As new kinds of windows are added to this application, this routine will have}
  298. {* to be able to detect the new kind of window and dispatch to the routine that}
  299. {* handles activate events in that kind of window.}
  300. {*******************************************************************************)
  301.  
  302.     procedure DoActivateEvt (eventWind: WindowPtr; becomingActive: Boolean);
  303.  
  304.     begin
  305.         if IsProcessListWindow(eventWind) then
  306.             ActivateProcessListWindow(eventWind, becomingActive);
  307.     end;
  308.  
  309.  
  310. {$S Main}
  311. (*******************************************************************************}
  312. {* Public: DoWindowClose}
  313. {*}
  314. {* As new kinds of windows are added to this application, this routine will have}
  315. {* to be able to detect the new kind of window and dispatch to the routine that}
  316. {* handles close requests for that kind of window.}
  317. {*******************************************************************************)
  318.  
  319.     procedure DoWindowClose (anEvent: EventRecord; eventWind: WindowPtr);
  320.  
  321.     begin
  322.         if TrackGoAway(eventWind, anEvent.where) then
  323.             if IsProcessInfoWindow(eventWind) then
  324.                 CloseProcessInfoWindow(eventWind);
  325.     end;
  326.  
  327.  
  328. {$S Main}
  329. (*******************************************************************************}
  330. {* DoMouseDown - Mouse-down event dispatcher}
  331. {*}
  332. {* When a mouseDown event is received in the main event loop, this routine is}
  333. {* called to determine which area on the screens the mouseDown was, and to}
  334. {* dispatch to the appropriate routine to handle mouseDown events in that area.}
  335. {* The mouseDown event is passed in the anEvent parameter.}
  336. {*}
  337. {* See the UMenuHandler unit for routines that handle mouse-down events in the}
  338. {* menu bar, and the UWindowHandler unit for routines that handle mouse-down}
  339. {* events in the windows.}
  340. {*******************************************************************************)
  341.  
  342.     procedure DoMouseDown (anEvent: EventRecord);
  343.  
  344.         var
  345.             clickArea: Integer;   {Area of the screen that was clicked}
  346.             eventWind: WindowPtr; {Pointer the clicked window, if any}
  347.  
  348.     begin
  349.         (* Find clicked area of screen or window *)
  350.         clickArea := FindWindow(anEvent.where, eventWind); (*<*)
  351.  
  352.         (* Jump to mouseDown-handling routine appropriate for screen area *)
  353.         case clickArea of
  354.             inMenuBar: 
  355.                 DoMenuChoice(MenuSelect(anEvent.where));
  356.             inContent: 
  357.                 DoContentClick(anEvent, eventWind);
  358.             inGoAway: 
  359.                 DoWindowClose(anEvent, eventWind);
  360.             inDrag: 
  361.                 DoWindowDrag(anEvent, eventWind)
  362.         end
  363.     end;
  364.  
  365.  
  366. {$S Main}
  367. (*******************************************************************************}
  368. {* DoKeyDown - Key-down event dispatcher}
  369. {*}
  370. {* When a keyDown or autoKey event is received in the main event loop, this}
  371. {* routine is called to determine whether key is a command-key equivalent for a}
  372. {* menu item or not.  If the command key isn’t down, then the key stroke is}
  373. {* ignored.  Otherwise, MenuKey is called to get the menu ID and item number}
  374. {* of the menu item that corresponds to the command key, if any.  Then}
  375. {* DoMenuChoice is called to dispatch to the appropriate routine for the chosen}
  376. {* menu item.  The keyDown or autoKey event is passed in anEvent.}
  377. {*}
  378. {* See the UMenuHandler unit for routines that handle menu events.}
  379. {*******************************************************************************)
  380.  
  381.     procedure DoKeyDown (anEvent: EventRecord);
  382.  
  383.         var
  384.             theKey: Char; {ASCII code of key that was pressed}
  385.  
  386.     begin
  387.         (* Get the ASCII code of the pressed key *)
  388.         theKey := CHR(BAND(anEvent.message, charCodeMask));
  389.  
  390.         (* If anEvent was keyDown and command key was down, it’s menu command *)
  391.         if (anEvent.what = keyDown) and (BAND(anEvent.modifiers, cmdKey) <> 0) then
  392.             DoMenuChoice(MenuKey(theKey))
  393.     end;
  394.  
  395.  
  396. {$S Main}
  397. (*******************************************************************************}
  398. {* DoDiskEvt - Handle a disk-insert event}
  399. {*}
  400. {* This routine is called whenever this application receives an event indicating}
  401. {* that a disk was inserted.  If the disk can’t be mounted, the message field of}
  402. {* the event reflects the error, and we call DIBadMount to allow the user to}
  403. {* format the disk.}
  404. {*******************************************************************************)
  405.  
  406.     procedure DoDiskEvt (anEvent: EventRecord);
  407.  
  408.         const
  409.             kSysAlertLeft = 80; {Left coord of DIBadMount alert in screen coords}
  410.             kSysAlertTop = 80; {Top coord of DIBadMount alert in screen coords}
  411.  
  412.         var
  413.             cornerPoint: Point; {Top-left corner of DIBadMount alert}
  414.             error: OSErr;
  415.  
  416.     begin
  417.         if HiWrd(anEvent.message) <> noErr then
  418.             begin
  419.                 SetPt(cornerPoint, kSysAlertLeft, kSysAlertTop);(*<*)
  420.                 error := DIBadMount(cornerPoint, anEvent.message)
  421.             end
  422.     end;
  423.  
  424.  
  425. {$S Main}
  426. (*******************************************************************************}
  427. {* Public: DoOSEvt}
  428. {*}
  429. {* When an OS Event is received, it can be a suspend or resume event.}
  430. {*******************************************************************************)
  431.  
  432.     procedure DoOSEvt (anEvent: EventRecord);
  433.  
  434.         var
  435.             eventWindow: WindowPtr; {Pointer to window being activated/deactivated}
  436.             osEvtKind: Byte;      {Kind of OSEvt; mouse-moved or suspend/resume}
  437.  
  438.     begin
  439.         (* Only care if anEvent is suspend/resume event *)
  440.         osEvtKind := BAND(BSR(anEvent.message, 24), $00FF);
  441.         if osEvtKind = suspendResumeMessage then
  442.             begin
  443.                 (* It’s a suspend/resume event; suspend or resume? *)
  444.                 eventWindow := FrontWindow;
  445.                 if BAND(anEvent.message, 1) <> 0 then
  446.                     begin
  447.                         (* Resume event; set the cursor and activate front window *)
  448.                         InitCursor;
  449.                         if eventWindow <> nil then
  450.                             DoActivateEvt(eventWindow, kBecomingActive);
  451.                         gWereInFront := TRUE
  452.                     end
  453.                 else
  454.                     begin
  455.                         (* Suspend event; deactivate the front window *)
  456.                         if eventWindow <> nil then
  457.                             DoActivateEvt(eventWindow, not kBecomingActive);
  458.                         gWereInFront := FALSE
  459.                     end
  460.             end
  461.     end;
  462.  
  463.  
  464. {$S Main}
  465. (*******************************************************************************}
  466. {* DoHighLevelEvent - Handle a high-level event}
  467. {*}
  468. {* This routine handles the high-level event specified by anEvent.  The only}
  469. {* high-level events that this application handles are AppleEvents, so I just}
  470. {* pass the high-level event to AEProcessAppleEvent.  AEProcessAppleEvent calls}
  471. {* the appropriate AppleEvent handler routine to handle that particular kind of}
  472. {* AppleEvent.}
  473. {*******************************************************************************)
  474.  
  475.     function AEProcessAppleEvent2 (theEventRecord: EventRecord): OSErr;
  476.     inline
  477.         $303C, $021B, $A816;
  478.  
  479.     procedure DoHighLevelEvent (anEvent: EventRecord);
  480.  
  481.         var
  482.             error: OSErr;
  483.     begin
  484.         error := AEProcessAppleEvent2(anEvent);
  485.     end;
  486.  
  487.  
  488. {$S Main}
  489. (*******************************************************************************}
  490. {* EventLoop - Main event loop for this application}
  491. {*}
  492. {* This is the main event loop of this application.  During every iteration of}
  493. {* the event loop, the menus are kept up-to-date, and the Process List window and}
  494. {* all of the open Process Information windows are given time to update}
  495. {* themselves to current conditions.  Also, NoEmergMem is called to detect}
  496. {* whether the emergency memory was used.  If it was, then RecoverEmergMem is}
  497. {* called in an attept to get it back.  If it can’t, then some commands could be}
  498. {* disabled until the memory can be recovered.}
  499. {*******************************************************************************)
  500.  
  501.     procedure EventLoop;
  502.  
  503.         var
  504.             anEvent: EventRecord; {An incoming event}
  505.  
  506.     begin
  507.         FixMenus;
  508.         InitCursor;
  509.         gWereInFront := WereInFront;
  510.         gQuitting := FALSE;
  511.  
  512.         (* We loop “forever,” or until the Quit handler calls ExitToShell *)
  513.         while not gQuitting do
  514.             begin
  515.                 (* Give all open windows some time *)
  516.                 IdleAllProcessWindows;
  517.  
  518.                 (* Try to reallocate emergency memory if it’s been used *)
  519.                 if NoEmergMem then
  520.                     RecoverEmergMem;
  521.  
  522.                 (* Fix the menus to reflect current conditions *)
  523.                 FixMenus;
  524.  
  525.                 (* It’s time to get and examine an event *)
  526.                 if WaitNextEvent(everyEvent, anEvent, kMaxSleepTime, nil) then (*<*)
  527.                     begin
  528.                         case anEvent.what of
  529.                             mouseDown: 
  530.                                 DoMouseDown(anEvent);
  531.                             keyDown, autoKey: 
  532.                                 DoKeyDown(anEvent);
  533.                             updateEvt: 
  534.                                 DoUpdateEvt(anEvent);
  535.                             diskEvt: 
  536.                                 DoDiskEvt(anEvent);
  537.                             activateEvt: 
  538.                                 DoActivateEvt(WindowPtr(anEvent.message), BAND(anEvent.modifiers, activeFlag) <> 0);
  539.                             osEvt: 
  540.                                 DoOSEvt(anEvent);
  541.                             kHighLevelEvent: 
  542.                                 DoHighLevelEvent(anEvent)
  543.                         end
  544.                     end
  545.             end
  546.     end;
  547.  
  548.  
  549. begin
  550.     (* Set up the heap *)
  551.     MaxApplZone;
  552.     MoreMasters;
  553.     MoreMasters;
  554.     MoreMasters;
  555.     MoreMasters;
  556.     MoreMasters;
  557.     MoreMasters;
  558.  
  559.     (* Do anything that must be done at program start-up *)
  560.     StartUp;
  561. {$IFC UNDEFINED THINK_PASCAL}
  562.     UnloadSeg(@StartUp);
  563. {$ENDC}
  564.  
  565.     (* Set the default launch mode *)
  566.     SetLaunchMode(kJustLaunch);
  567.  
  568.     (* Open the process list window *)
  569.     gProcessListWind := CreateProcessListWindow;
  570.  
  571.     (* Enter the main event loop *)
  572.     EventLoop
  573. end.